package com.yalu.file;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.yalu.entity.BillData;
import com.yalu.entity.BillDetailData;
import com.yalu.entity.BillDetailDataExcel;
import com.yalu.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.io.RandomAccessFile;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 未知
 */
@Slf4j
@Component
public class PtPdfRead {

    /**
     * 读PDF文件，使用了pdfbox开源项目
     *
     * @param fileName
     */
    public static void readPdf(String fileName, String year, Map<String, BillData> map) {
        File file = new File(fileName);
        FileInputStream in = null;
        try {
            in = new FileInputStream(fileName);
            // 新建一个PDF解析器对象
            PDFParser parser = new PDFParser(new RandomAccessFile(file, "r"));
            // 对PDF文件进行解析
            parser.parse();
            // 获取解析后得到的PDF文档对象
            PDDocument pdfdocument = parser.getPDDocument();
            int pageSize = pdfdocument.getNumberOfPages();
            boolean isStart = false;
            for (int i = 0; i < pageSize; i++) {
                // 新建一个PDF文本剥离器
                PDFTextStripper stripper = new PDFTextStripper();
                // 设置按顺序输出
                stripper.setSortByPosition(true);
                stripper.setStartPage(i + 1);
                stripper.setEndPage(i + 1);
                String lineSepartor = stripper.getLineSeparator();
                // 从PDF文档对象中剥离文本
                String result = stripper.getText(pdfdocument);
                String[] resultArray = result.split(lineSepartor);
                int arrayLength = resultArray.length;
                Queue<BillDetailData> dataQueue = new LinkedList<>();
                for (int y = 0; y < arrayLength; y++) {
                    String lineText = resultArray[y];
                    if (null == lineText || "".equals(lineText.trim()) || lineText.contains("Total")) {
                        continue;
                    }
                    if (lineText.contains("Thank you")) {
                        break;
                    }
                    if ("地区 账号Id 店铺名称 收款机构 收款账号 到账币种 到账金额 费用 优惠金额 店铺余额 汇率".equals(lineText) || "序号 创建时间 出/入账 业务类型 出/入账币种 出/入账 交易Id 平台 店铺所在金额 地区 账号Id 店铺名称 收款机构 收款账号 到账币种 到账金额 费用 优惠金额 店铺余额 汇率".equals(lineText)) {
                        isStart = true;
                    } else {
                        if (isStart) {
                            Pattern pattern = Pattern.compile(CommonUtil.AMOUNT_MATCHES);
                            Matcher matcher = pattern.matcher(lineText.replace(",", ""));
                            if (!matcher.find()) {
                                log.warn("未找到金额：{}", lineText);
                                continue;
                            }
                            String[] lineTextArray = lineText.split(" ");
                            boolean isBalanceData = true;
                            String balance = null;
                            while (isBalanceData) {
                                String lineTextTemp = resultArray[y];
                                String[] lineTextTempArray = lineTextTemp.split(" ");
                                int lengthTemp = lineTextTempArray.length;
                                balance = lineTextTempArray[lengthTemp - 1].replace(",", "").trim();
                                if ("1".equals(balance)) {
                                    balance = lineTextTempArray[lengthTemp - 2].replace(",", "").trim();
                                }
                                Matcher matcherBalance = CommonUtil.PATTERN.matcher(balance);
                                if (matcherBalance.find()) {
                                    isBalanceData = false;
                                } else {
                                    y++;
                                    if (y >= arrayLength) {
                                        isBalanceData = false;
                                    }
                                }
                            }
                            if (balance.startsWith("0.008")) {
                                y++;
                                continue;
                            }
                            Integer orderNum = Integer.valueOf(lineTextArray[0].trim());
                            String currency = lineTextArray[5];
                            if (53 == orderNum) {
                                currency = "USD";
                            } else if (924 == orderNum) {
                                currency = "JPY";
                            }
                            BillData billData = new BillData();
                            billData.setCurrency(currency);
                            billData.setType("Savings");
                            String key = billData.getCurrency().concat(billData.getType());
                            BillData mapBillData = map.get(key);
                            if (null == mapBillData) {
                                List<BillDetailData> list = new ArrayList<>();
                                billData.setDetailData(list);
                                map.put(key, billData);
                            } else {
                                billData = mapBillData;
                            }
                            BillDetailData detailDataQueue = dataQueue.poll();
                            dataQueue.offer(detailDataQueue);
                            BillDetailData detailData = new BillDetailData();
                            if (null != detailDataQueue) {
                                dataQueue.poll();
                                BeanUtils.copyProperties(detailDataQueue, detailData);
                                dataQueue.offer(detailData);
                            }
                            detailData.setDate(lineTextArray[1].trim());
                            String amount = lineTextArray[6].replace(",", "").trim();
                            detailData.setBalance(balance);
                            detailData.setOrderNumber(Integer.valueOf(lineTextArray[0].trim()));
                            if ("入账".equals(lineTextArray[3].trim())) {
                                detailData.setDeposit(amount);
                                detailData.setTransactionDetails("入账");
                            } else {
                                detailData.setWithdrawal(amount);
                                detailData.setTransactionDetails("出账");
                            }
                            if (StringUtils.hasText(detailData.getTransactionDetails()) && (StringUtils.hasText(detailData.getBalance()) || StringUtils.hasText(detailData.getDeposit()) || StringUtils.hasText(detailData.getWithdrawal()))) {
                                billData.getDetailData().add(detailData);
                                dataQueue.poll();
                                detailData = new BillDetailData();
                                dataQueue.offer(detailData);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("读取PDF文件" + file.getAbsolutePath() + "生失败！" + e);
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                }
            }
        }
    }

    /**
     * 测试pdf文件的创建
     *
     * @param args
     */
    public static void main(String[] args) {
        String filePath = "D://yalu//monthly//";  //这里先手动把绝对路径的文件夹给补上。
        LinkedList<String> filePaths = new LinkedList<>();
        recursionFile(filePath, filePaths);
        System.out.println("文件数量：" + filePaths.size());
        Map<String, BillData> map = new HashMap<>();
        String year = "";
        for (String fileName : filePaths) {
            int lastIndex = fileName.lastIndexOf("\\");
            year = fileName.substring(lastIndex + 1, lastIndex + 5);
            readPdf(fileName, year, map);
        }
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String time = LocalDateTime.now().format(dtf);
        String outFileName = "D:\\yalu\\" + year + "年_月结单_未知_" + time.substring(time.length() - 6) + ".xlsx";
        writerFils(map, outFileName);
    }

    /**
     * 写入文件
     *
     * @param map
     * @param outFileName
     */
    public static void writerFils(Map<String, BillData> map, String outFileName) {
        try {
            ExcelWriter excelWriter = EasyExcel.write(outFileName, BillDetailDataExcel.class).build();
            for (String key : map.keySet()) {
                BillData billData = map.get(key);
                String sheetName = "1";
                if ("Savings".equals(billData.getType())) {
                    sheetName = "月结单（" + billData.getCurrency() + "）";
                } else if ("Current".equals(billData.getType())) {
                    sheetName = "资金往来（" + billData.getCurrency() + "）";
                }
                BigDecimal depositSum = new BigDecimal(0);
                BigDecimal withdrawalSum = new BigDecimal(0);
                int size = billData.getDetailData().size();
                List<BillDetailDataExcel> list = new ArrayList<>(size);
                int start = size - 1;
                for (int i = start; i >= 0; i--) {
                    BillDetailData billDetailData = billData.getDetailData().get(i);
                    BillDetailDataExcel billDetailDataExcel = new BillDetailDataExcel();
                    BeanUtils.copyProperties(billDetailData, billDetailDataExcel);
                    if (StringUtils.hasText(billDetailData.getDeposit())) {
                        depositSum = depositSum.add(new BigDecimal(billDetailData.getDeposit()));
                    }
                    if (StringUtils.hasText(billDetailData.getWithdrawal())) {
                        withdrawalSum = withdrawalSum.add(new BigDecimal(billDetailData.getWithdrawal()));
                    }
                    billDetailDataExcel.setOrder(String.valueOf(billDetailData.getOrderNumber()));
                    log.info("数据：{}", billDetailDataExcel);
                    list.add(billDetailDataExcel);
                }
                if (0 < list.size()) {
                    BillDetailDataExcel billDetailDataExcel = new BillDetailDataExcel();
                    billDetailDataExcel.setDate("智能校对助手校对结果");
                    billDetailDataExcel.setDeposit("总收入：" + depositSum.toString());
                    billDetailDataExcel.setWithdrawal("总支出：" + withdrawalSum.toString());
                    list.add(billDetailDataExcel);
                }
                WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
                excelWriter.write(list, writeSheet);
            }
            // 千万别忘记finish 会帮忙关闭流
            excelWriter.finish();
        } catch (Exception e) {
            log.error("文件写入失败：", e);
        }
    }

    /**
     * 递归文件
     *
     * @param path
     * @param filePaths
     */
    public static void recursionFile(String path, LinkedList<String> filePaths) {
        if (StringUtils.hasText(path)) {
            File file = new File(path);
            for (File f : file.listFiles()) {
                if (f.isDirectory()) {
                    recursionFile(f.getPath(), filePaths);
                } else {
                    if (f.getPath().contains(".pdf")) {
                        filePaths.add(f.getPath());
                    }
                }
            }
        }
    }

}
